﻿using System.IO.Pipes;
using System.IO;
using System.Threading.Tasks;
namespace Yt.Core.IPC.NamedPipe
{
    /// <summary>
    /// 命名管道服务端
    /// </summary>
    internal class PipeServerBuilder:PipeBuilderBase
    { 
        protected  PipeServerBuilder(string pipeName) : base(pipeName)
        {
            pipeStream = CreateNamedPipeServer(pipeName);
        }
        /// <summary>
        /// 创建命名管道服务端实例
        /// </summary>
        /// <param name="pipeName">管道名称</param>
        /// <returns></returns>
        internal static PipeBuilderBase CreateBuilder(string pipeName)
        {
             return new PipeServerBuilder(pipeName);        
        }
        private NamedPipeServerStream CreateNamedPipeServer(string pipeName)
        {
            PipeSecurity pse = new PipeSecurity();
            pse.SetAccessRule(new PipeAccessRule("Everyone", PipeAccessRights.ReadWrite, System.Security.AccessControl.AccessControlType.Allow));

            pipeStream = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 2, PipeTransmissionMode.Message, PipeOptions.Asynchronous,
             int.MaxValue, int.MaxValue,  pse, System.IO.HandleInheritability.None) ;
          
            return pipeStream as NamedPipeServerStream; 
        }
        /// <summary>
        /// 连接管道，开始工作,用于服务端
        /// </summary>
        public override void Connect()
        {
            ((NamedPipeServerStream)pipeStream).WaitForConnectionAsync();
            ((NamedPipeServerStream)pipeStream).BeginWaitForConnection(
              (p) =>
              {
                  streamWriter = new StreamWriter(pipeStream);
                  streamReader = new StreamReader(pipeStream);
                  OnConnection?.BeginInvoke(null, null);
                  Task.Run(() =>
                  {
                      while (true)
                      {
                          if (!pipeStream.IsConnected)
                          {
                              OnDisconnect?.BeginInvoke(null, null);
                              break;
                          }
                          System.Threading.Thread.Sleep(10);
                          System.Windows.Forms.Application.DoEvents();
                      }
                  });
                  Task.Run(() =>
                  {
                      DoReadLine();
                  });
              }
               , null);
        }
        ~PipeServerBuilder()
        {
            Dispose();
        }
    }
}
